#include <linux/device.h>
#include <linux/usb/composite.h>

extern const struct usb_descriptor_header *otg_desc[];

#include "gadget_chips.h"

#ifdef CONFIG_USB_OTG
static struct usb_otg_descriptor otg_descriptor = {
	.bLength =		sizeof otg_descriptor,
	.bDescriptorType =	USB_DT_OTG,

	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
};

const struct usb_descriptor_header *otg_desc[] = {
	(struct usb_descriptor_header *) &otg_descriptor,
	NULL,
};
#endif

#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"

#include "dummy_config.c"

#define DRIVER_VENDOR_NUM	0x0606
#define DRIVER_PRODUCT_NUM	0x0606

static struct usb_device_descriptor device_desc = {
	.bLength =		sizeof device_desc,
	.bDescriptorType =	USB_DT_DEVICE,

	.bcdUSB =		__constant_cpu_to_le16(0x0200),
	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,

	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
	.bNumConfigurations =	1,
};

#define STRING_MANUFACTURER_IDX		0
#define STRING_PRODUCT_IDX		1
#define STRING_SERIAL_IDX		2

static struct usb_string strings_dev[] = {
	[STRING_MANUFACTURER_IDX].s = "Shanghai Jiao Tong University",
	[STRING_PRODUCT_IDX].s = "Gadget nothing",
	[STRING_SERIAL_IDX].s = "0123456789.0123456789.0123456789",
	{  }
};

static struct usb_gadget_strings stringtab_dev = {
	.language	= 0x0409,
	.strings	= strings_dev,
};

static struct usb_gadget_strings *dev_strings[] = {
	&stringtab_dev,
	NULL,
};

static int __init nothing_bind(struct usb_composite_dev *cdev)
{
	int			gcnum;
	struct usb_gadget	*gadget = cdev->gadget;
	int			id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_MANUFACTURER_IDX].id = id;
	device_desc.iManufacturer = id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_PRODUCT_IDX].id = id;
	device_desc.iProduct = id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_SERIAL_IDX].id = id;
	device_desc.iSerialNumber = id;

	dummy_add(cdev);

	gcnum = usb_gadget_controller_number(gadget);
	if (gcnum >= 0)
		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
	else
		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);

	return 0;
}

static struct usb_composite_driver nothing_driver = {
	.name		= "nothing",
	.dev		= &device_desc,
	.strings	= dev_strings,
	.bind		= nothing_bind,
};

MODULE_LICENSE("GPL");

static int __init init(void)
{
	return usb_composite_register(&nothing_driver);
}
module_init(init);

static void __exit cleanup(void)
{
	usb_composite_unregister(&nothing_driver);
}
module_exit(cleanup);
